package cn.edu.xmu.orderpayment.payment.dao;

import cn.edu.xmu.oomall.core.util.ReturnNo;
import cn.edu.xmu.oomall.core.util.ReturnObject;
import cn.edu.xmu.orderpayment.payment.mapper.ErrorAccountPoMapper;
import cn.edu.xmu.orderpayment.payment.mapper.PaymentPatternPoMapper;
import cn.edu.xmu.orderpayment.payment.mapper.PaymentPoMapper;
import cn.edu.xmu.orderpayment.payment.mapper.RefundPoMapper;
import cn.edu.xmu.orderpayment.payment.model.bo.ErrorAccount;
import cn.edu.xmu.orderpayment.payment.model.bo.PayPattern;
import cn.edu.xmu.orderpayment.payment.model.bo.Payment;
import cn.edu.xmu.orderpayment.payment.model.bo.Refund;
import cn.edu.xmu.orderpayment.payment.model.po.*;
import cn.edu.xmu.orderpayment.payment.model.vo.*;
import cn.edu.xmu.orderpayment.payment.util.PayMentPatternLoader;
import cn.edu.xmu.orderpayment.payment.util.paypattern.BasePaymentPattern;
import cn.edu.xmu.orderpayment.payment.model.po.*;
import cn.edu.xmu.privilegegateway.annotation.util.Common;
import cn.edu.xmu.orderpayment.payment.model.po.ErrorAccountPo;
import cn.edu.xmu.orderpayment.payment.model.po.PaymentPatternPo;
import cn.edu.xmu.orderpayment.payment.model.po.PaymentPo;
import cn.edu.xmu.orderpayment.payment.model.po.RefundPo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static cn.edu.xmu.privilegegateway.annotation.util.Common.*;

/**
 * @author yunlong
 * @date 2021-12-02
 */
@Repository
public class PayDao {

    private Logger logger = LoggerFactory.getLogger(PayDao.class);
    @Autowired
    private PaymentPoMapper paymentPoMapper;
    @Autowired
    private RefundPoMapper refundPoMapper;
    @Autowired
    private ErrorAccountPoMapper errorAccountPoMapper;

    @Autowired
    private PaymentPatternPoMapper paymentPatternPoMapper;



    public ReturnObject getValidPaymentPattern() {

        try {
            PaymentPatternPoExample example = new PaymentPatternPoExample();
            PaymentPatternPoExample.Criteria criteria = example.createCriteria();
            criteria.andStateEqualTo(PayPattern.State.USABLE.getCode().byteValue());
            criteria.andBeginTimeLessThanOrEqualTo(LocalDateTime.now());
            criteria.andEndTimeGreaterThan(LocalDateTime.now());
            List<PaymentPatternPo> paymentPatternPoList = paymentPatternPoMapper.selectByExample(example);
            if (paymentPatternPoList == null || paymentPatternPoList.size() == 0) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST, "沒有可用支付渠道");//TODO 不知道返回值些什么
            }
            List<SimplePayPatternRetVo> simplePayPatternRetVoList = new ArrayList<>();
            for (PaymentPatternPo paymentPatternPo : paymentPatternPoList) {
                simplePayPatternRetVoList.add(Common.cloneVo(paymentPatternPo, SimplePayPatternRetVo.class));
            }

            return new ReturnObject(simplePayPatternRetVoList);
        } catch (Exception e) {
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }


    public ReturnObject getPayPatterns() {
        try {
            PaymentPatternPoExample example = new PaymentPatternPoExample();
            PaymentPatternPoExample.Criteria criteria = example.createCriteria();
            criteria.andIdIsNotNull();//查全部
            List<PaymentPatternPo> paymentPatternPoList = paymentPatternPoMapper.selectByExample(example);
            List<PayPatternRetVo> payPatternRetVoList =new ArrayList<>();
            for (PaymentPatternPo paymentPatternPo : paymentPatternPoList) {
                PayPatternRetVo payPatternRetVo=cloneVo(paymentPatternPo,PayPatternRetVo.class);
                payPatternRetVo.setModifier(new SimpleAdminUserVo(paymentPatternPo.getCreatorId(),paymentPatternPo.getCreatorName()));
                payPatternRetVo.setCreator(new SimpleAdminUserVo(paymentPatternPo.getModifierId(), paymentPatternPo.getModifierName()));
                payPatternRetVoList.add(payPatternRetVo);
            }
            return new ReturnObject(payPatternRetVoList);

        } catch (Exception e) {
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 平台管理员查询支付信息
     * 查询条件：单据ID，状态，晚于此支付时间，早于此支付时间，页码，页数
     * 不返回已被逻辑删除的支付信息，按照时间倒序
     *
     * 利用Mapper的select和PoExample配合
     * @return Array(SimplePayment)
     */
    public ReturnObject getPaymentInfo(PaymentPoExample example, Integer page,Integer pageSize) {

        try {
            PageHelper.startPage(page, pageSize);
            List<PaymentPo> poList = paymentPoMapper.selectByExample(example);
            List<SimplePaymentRetVo> simplePaymentRetVoList = new ArrayList<>();
            for (PaymentPo paymentPo : poList) {
                simplePaymentRetVoList.add( cloneVo(paymentPo,SimplePaymentRetVo.class));
            }

            PageInfo pageInfo = PageInfo.of(poList);
            pageInfo.setList(simplePaymentRetVoList);
            return new ReturnObject(pageInfo);

        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 平台管理员查询支付单信息详情
     * 查询条件：支付单ID
     * 不返回已被逻辑删除的支付单信息
     *
     * 利用Mapper的select和PoExample配合
     * @return Payment
     * @author wang xusheng
     */
    public ReturnObject getPaymentDetailInfo(Long id) {
        try {
            PaymentPo paymentPo = paymentPoMapper.selectByPrimaryKey(id);
            if (paymentPo == null) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST, "支付信息不存在");
            }
            Payment payment = cloneVo(paymentPo, Payment.class);
            return new ReturnObject(payment);
        } catch (Exception e) {
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject<List> getPaymentByDocumentId(String documentId) {
        try {
            PaymentPoExample example = new PaymentPoExample();
            PaymentPoExample.Criteria criteria = example.createCriteria();
            criteria.andDocumentIdEqualTo(documentId);
            List<PaymentPo> list = paymentPoMapper.selectByExample(example);
            if (list.size() == 0) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST, "支付信息不存在");
            }
            return new ReturnObject(list);
        } catch (Exception e) {
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject<List> getPaymentByExample(PaymentPoExample paymentPoExample) {
        try {
            List<PaymentPo> list = paymentPoMapper.selectByExample(paymentPoExample);
            if (list.size() == 0) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST, "支付信息不存在");
            }
            return new ReturnObject(list);
        } catch (Exception e) {
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }


    /**
     * 平台管理员修改支付单信息
     * @return
     * @author wang xusheng
     */
    public ReturnObject modifyPaymentInfo(Payment paymentBo, Long loginId, String loginName) {
        try {
            PaymentPo paymentPo = cloneVo(paymentBo, PaymentPo.class);
            setPoModifiedFields(paymentPo, loginId, loginName);
            paymentPoMapper.updateByPrimaryKeySelective(paymentPo);
            return new ReturnObject(paymentPoMapper.selectByPrimaryKey(paymentBo.getId()));
        } catch (Exception e) {
            logger.error("PayDao.modifyPaymentInfo:" + e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 平台管理员查询退款信息
     * 查询条件：单据ID，状态，晚于此退款时间，早于此退款时间，页码，页数
     * 不返回已被逻辑删除的退款信息，按照时间倒序
     *
     * 利用Mapper的select和PoExample配合
     * @return Array(SimpleRefund)
     */
    public ReturnObject getRefundInfo(RefundPoExample example,Integer page,Integer pageSize) {

        try {
            PageHelper.startPage(page, pageSize);
            List<RefundPo> poList = refundPoMapper.selectByExample(example);
            List<SimpleRefundRetVo> voList = new ArrayList<>();
            for (RefundPo refundPo : poList) {
                voList.add( cloneVo(refundPo,SimpleRefundRetVo.class));
            }

            PageInfo pageInfo = PageInfo.of(poList);
            pageInfo.setList(voList);
            return new ReturnObject(pageInfo);

        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 平台管理员通过id查询退款详细信息
     * 查询条件：单据ID
     * 利用Mapper的selectByPrimaryKey
     * @return Refund
     * @author wang xusheng
     */
    public ReturnObject getRefundDetailInfo(Long id) {
        try {
            RefundPo refundPo = refundPoMapper.selectByPrimaryKey(id);
            if (refundPo == null) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST, "退款信息不存在");
            }
            Refund refund = cloneVo(refundPo, Refund.class);
            return new ReturnObject(refund);
        } catch (Exception e) {
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 平台管理员修改退款单信息
     * @return
     * @author wang xusheng
     */
    public ReturnObject modifyRefundInfo(Refund refundBo, Long loginId, String loginName) {
        try {
            RefundPo refundPo = cloneVo(refundBo, RefundPo.class);
            setPoModifiedFields(refundPo, loginId, loginName);
            refundPoMapper.updateByPrimaryKeySelective(refundPo);
            return new ReturnObject(refundPoMapper.selectByPrimaryKey(refundPo.getId()));
        } catch (Exception e) {
            logger.error("PayDao.modifyRefundInfo:" + e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 平台管理员查询错帐信息
     * 查询条件：单据ID，状态，晚于此账目时间，早于此账目时间，页码，页数
     *
     * 利用Mapper的select和PoExample配合
     * @return Array(SimpleErrorAccount)
     */
    public ReturnObject getErrorAccount(ErrorAccountPoExample example,Integer page,Integer pageSize) {
        try {
            PageHelper.startPage(page, pageSize);
            List<ErrorAccountPo> poList = errorAccountPoMapper.selectByExample(example);
            List<SimpleErrorAccountRetVo> voList = new ArrayList<>();
            for (ErrorAccountPo errorAccountPo : poList) {
                voList.add( cloneVo(errorAccountPo,SimpleErrorAccountRetVo.class));
            }

            PageInfo pageInfo = PageInfo.of(poList);
            pageInfo.setList(voList);
            return new ReturnObject(pageInfo);

        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 平台管理员通过id查询错账详细信息
     * 查询条件：单据ID
     * 利用Mapper的selectByPrimaryKey
     *
     * @return Refund
     */
    public ReturnObject getErrorAccountDetailInfo(Long id){
        try{
            ErrorAccountPo errorAccountPo = errorAccountPoMapper.selectByPrimaryKey(id);
            if(errorAccountPo == null){
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST,"错账信息不存在");
            }
            ErrorAccount errorAccount = cloneVo(errorAccountPo, ErrorAccount.class);
            return new ReturnObject(errorAccount);
        } catch (Exception e) {
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 平台管理员修改错账单信息
     * @return
     * @author wang xusheng
     */
    public ReturnObject modifyErrorAccountInfo(ErrorAccount errorAccountBo, Long loginId, String loginName) {
        try {
            ErrorAccountPo errorAccountPo = cloneVo(errorAccountBo, ErrorAccountPo.class);
            setPoModifiedFields(errorAccountPo, loginId, loginName);
            errorAccountPoMapper.updateByPrimaryKeySelective(errorAccountPo);
            return new ReturnObject(errorAccountPoMapper.selectByPrimaryKey(errorAccountPo.getId()));
        } catch (Exception e) {
            logger.error("PayDao.modifyErrorAccountInfo:" + e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject getPayPatternById(Long patternId) {
        try{
            PaymentPatternPo po=paymentPatternPoMapper.selectByPrimaryKey(patternId);
            if(po==null)return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST,"该支付方式不存在");
            return new ReturnObject<>(cloneVo(po,PayPattern.class));
        }
        catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 获取某个时间段内的支付单
     * @param beginTime
     * @param endTime
     * @return
     * @author wang xusheng
     */
    public ReturnObject getPaymentsByTime(ZonedDateTime beginTime, ZonedDateTime endTime){
        try {
            PaymentPoExample paymentPoExample = new PaymentPoExample();
            PaymentPoExample.Criteria criteria = paymentPoExample.createCriteria();
            if (beginTime != null) {
                criteria.andPayTimeGreaterThanOrEqualTo(beginTime.withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime());
            }
            if (endTime != null) {
                criteria.andPayTimeLessThanOrEqualTo(endTime.withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime());
            }
            List<PaymentPo> paymentPos = paymentPoMapper.selectByExample(paymentPoExample);
            List<Payment> payments = new ArrayList<>(paymentPos.size());
            for(PaymentPo paymentPo:paymentPos){
                payments.add(cloneVo(paymentPo,Payment.class));
            }
            return new ReturnObject(payments);
        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    /**
     * 获取某个时间段内的退款单
     * @param beginTime
     * @param endTime
     * @return
     * @author wang xusheng
     */
    public ReturnObject getRefundsByTime(ZonedDateTime beginTime, ZonedDateTime endTime){
        try {
            RefundPoExample refundPoExample = new RefundPoExample();
            RefundPoExample.Criteria criteria = refundPoExample.createCriteria();
            if (beginTime != null) {
                criteria.andRefundTimeGreaterThanOrEqualTo(beginTime.withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime());
            }
            if (endTime != null) {
                criteria.andRefundTimeLessThanOrEqualTo(endTime.withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime());
            }
            List<RefundPo> refundPos = refundPoMapper.selectByExample(refundPoExample);
            List<Refund> refunds = new ArrayList<>(refundPos.size());
            for(RefundPo refundPo:refundPos){
                refunds.add(cloneVo(refundPo,Refund.class));
            }
            return new ReturnObject(refunds);
        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }



    /**
     * 修改支付单为已对账
     * @param payment
     * @return
     * @author wang xusheng
     */
    public ReturnObject setPaymentReconciled(Payment payment){
        try{
            PaymentPo paymentPo = cloneVo(payment, PaymentPo.class);
            paymentPoMapper.updateByPrimaryKeySelective(paymentPo);
            return new ReturnObject(ReturnNo.OK);
        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR,e.getMessage());
        }
    }

    /**
     * 修改退款单为已对账
     * @param refund
     * @return
     * @author wang xusheng
     */
    public ReturnObject setRefundReconciled(Refund refund){
        try{
            RefundPo refundPo = cloneVo(refund, RefundPo.class);
            refundPoMapper.updateByPrimaryKeySelective(refundPo);
            return new ReturnObject(ReturnNo.OK);
        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR,e.getMessage());
        }
    }

    /**
     * 添加错账
     * @param errorAccount
     * @return
     * @author wang xusheng
     */
    public ReturnObject addErrorAccount(ErrorAccount errorAccount,Long loginId, String loginName) {
        try{
            ErrorAccountPo errorAccountPo = cloneVo(errorAccount,ErrorAccountPo.class);
            setPoCreatedFields(errorAccountPo,loginId,loginName);
            errorAccountPoMapper.insert(errorAccountPo);
            return new ReturnObject(ReturnNo.OK);
        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR,e.getMessage());
        }
    }

    public ReturnObject createPayment(Payment payment) {
        try{
            PaymentPo po=cloneVo(payment,PaymentPo.class);
            paymentPoMapper.insertSelective(po);
            Payment payment1=cloneVo(po,Payment.class);
            return new ReturnObject<>(payment1);
        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR,e.getMessage());
        }
    }

    public ReturnObject getPaymentById(Long pid) {
        try{
            PaymentPo po=  paymentPoMapper.selectByPrimaryKey(pid);
            if(po==null)
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST,"该支付单不存在");
            Payment payment=cloneVo(po,Payment.class);
            return new ReturnObject<>(payment);
        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR,e.getMessage());
        }
    }

    public ReturnObject<List<RefundPo>> getRefundByDocumentId(String documentId) {
        try {
            RefundPoExample example = new RefundPoExample();
            RefundPoExample.Criteria criteria = example.createCriteria();
            criteria.andDocumentIdEqualTo(documentId);
            List<RefundPo> list = refundPoMapper.selectByExample(example);
            if (list.size() == 0) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST, "退款信息不存在");
            }
            return new ReturnObject(list);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject<Refund> createRefund(Refund refund) {
        try{
            RefundPo refundPo=cloneVo(refund,RefundPo.class);
            refundPoMapper.insert(refundPo);
            return new ReturnObject<>(cloneVo(refundPo,Refund.class));

        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject getRefundById(Long id) {
        try{
            RefundPo po=  refundPoMapper.selectByPrimaryKey(id);
            if(po==null)
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST,"该支付单不存在");
            Refund refund=cloneVo(po,Refund.class);
            return new ReturnObject<>(refund);
        }catch (Exception e){
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR,e.getMessage());
        }
    }
}
